home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
pcr
/
pcr4_4.lha
/
DIST
/
threads
/
ThreadsOrders.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-02-18
|
8KB
|
256 lines
/* begincopyright
Copyright (c) 1988 Xerox Corporation. All rights reserved.
Use and copying of this software and preparation of derivative works based
upon this software are permitted. Any distribution of this software or
derivative works must comply with all applicable United States export
control laws. This software is made available AS IS, and Xerox Corporation
makes no warranty about the software, its performance or its conformity to
any specification. Any person obtaining a copy of this software is requested
to send their name and post office or electronic mail address to:
PCR Coordinator
Xerox PARC
3333 Coyote Hill Rd.
Palo Alto, CA
endcopyright */
/*
* ThreadsOrders.c
*
* Demers, June 15, 1990 4:12:18 pm PDT
* Boehm, August 16, 1991 11:18:14 am PDT
*/
#include "xr/BasicTypes.h"
#include "xr/Threads.h"
#include "xr/ThreadsBackdoor.h"
#include "xr/ThreadsPrivate.h"
#include "xr/ThreadsSignalsPrivate.h"
#include "xr/ThreadsMsgPrivate.h"
extern XR_VPE XR_NakedNotifyInner(/* XR_CV cv */); /* ThreadsPrivate.h */
/*
* VProcessor orders
*/
void
XR_IssueVPOrder (order, proc, stop)
XR_VPOrder order;
void (*proc)(/* order */);
bool stop;
{
order->vpo_proc = proc;
order->vpo_stop = stop;
if( XR_sysArea->sa_vpOrderMaster != XR_iope ) {
XR_PSem(&(XR_sysArea->sa_vpOrderSem), XR_VP_ORDER_SEM_LOCK, 1);
XR_sysArea->sa_vpOrderMaster = XR_iope;
}
XR_sysArea->sa_vpOrder = order;
XR_sysArea->sa_vpOrderNum++;
XR_RequestResched(NIL);
XR_PSem(&(XR_sysArea->sa_vpOrderSem), XR_VP_ORDER_SEM_WAIT,
XR_sysArea->sa_numVP);
if( ! stop ) {
XR_sysArea->sa_vpOrderMaster = NIL;
XR_VSem(&(XR_sysArea->sa_vpOrderSem), XR_VP_ORDER_SEM_LOCK, 1);
}
}
/*
* IOProcessor orders
*/
#define IOPODONE_INIT FALSE
#define IOPODONE_FINISHING ((bool)(2))
#define IOPODONE_DONE ((bool)(1))
XR_Thread XR_holderOfIOPOrderLocks = NIL;
void
XR_AcquireIOPOrderLocks ()
{
XR_IOPE iope, iopeLim;
iopeLim = &(XR_sysArea->sa_iope[XR_maxIOPs]);
for( iope = XR_sysArea->sa_iope; iope < iopeLim; iope++ ) {
XR_MonitorEntry( &(iope->iope_orderLock) );
}
if( XR_holderOfIOPOrderLocks != NIL )
XR_Panic("AcquireIOPOrderLocks 0");
XR_holderOfIOPOrderLocks = XR_currThread;
}
void
XR_ReleaseIOPOrderLocks ()
{
XR_IOPE iope, iopeLim;
if( XR_holderOfIOPOrderLocks != XR_currThread )
XR_Panic("ReleaseIOPOrderLocks 0");
XR_holderOfIOPOrderLocks = NIL;
iopeLim = &(XR_sysArea->sa_iope[XR_maxIOPs]);
for( iope = XR_sysArea->sa_iope; iope < iopeLim; iope++ ) {
XR_MonitorExit( &(iope->iope_orderLock) );
}
}
XR_IOPOResult
XR_IssueIOPOrder (iop, order, proc, cancel, abortable, timeout)
XR_IOPE iop;
XR_IOPOrder order;
void (*proc)(/* order */);
void (*cancel)(/* order */);
bool abortable;
XR_Ticks timeout;
{
int ans;
XR_InitializeCondition( &(order->iopo_cv), timeout );
if( abortable ) XR_EnableAborts( &(order->iopo_cv) );
order->iopo_done = IOPODONE_INIT;
order->iopo_next = NIL;
order->iopo_cancel = NIL;
order->iopo_proc = proc;
if( XR_holderOfIOPOrderLocks != XR_currThread )
XR_MonitorEntry( &(iop->iope_orderLock) );
XR_ASSERT( (iop->iope_order == NIL), "IssueIOPOrder a0" );
iop->iope_order = order;
if( kill(iop->iope_pid, XR_SIG_RESCHED) < 0 ) {
XR_ConsoleMsg("%? kill(pid:%d,sig:%d) failed err %d\n",
iop->iope_pid, XR_SIG_RESCHED, XR_GetErrno() );
XR_Panic("IssueIOPOrder 0");
}
(void) XR_WaitCV( &(iop->iope_orderAccepted), NIL );
if( XR_holderOfIOPOrderLocks != XR_currThread )
XR_MonitorExit( &(iop->iope_orderLock) );
ans = XR_WaitCV( &(order->iopo_cv), NIL );
if( ans == 0 ) {
if( order->iopo_done != IOPODONE_INIT ) {
while( order->iopo_done != IOPODONE_DONE ) {
XR_SpinStep(1000);
}
return XR_IOPO_RESULT_OK;
}
}
/*
* order failed, cancel it ...
*/
if( cancel != NIL ) {
order->iopo_cancel = cancel;
if( XR_holderOfIOPOrderLocks != XR_currThread )
XR_MonitorEntry( &(iop->iope_orderLock) );
XR_ASSERT( (iop->iope_order == NIL), "IssueIOPOrder a1" );
iop->iope_order = order;
if( kill(iop->iope_pid, XR_SIG_RESCHED) < 0 )
XR_Panic("IssueIOPOrder 1");
(void) XR_WaitCV( &(iop->iope_orderAccepted), NIL );
if( XR_holderOfIOPOrderLocks != XR_currThread )
XR_MonitorExit( &(iop->iope_orderLock) );
}
return( (ans != 0) ? XR_IOPO_RESULT_ABORTED : XR_IOPO_RESULT_TIMEDOUT );
}
XR_IOPOResult
XR_IssueIOPOrders (order, remoteProc, localProc)
XR_IOPOrder order;
void (*remoteProc)(/* order */);
void (*localProc)(/* order, iope */);
{
int ans,i;
XR_IOPE iope, iopeLim;
XR_IOPOrder iopo;
struct XR_IOPOrderRep iopor[XR_MAX_IOPS];
iopeLim = &(XR_sysArea->sa_iope[XR_maxIOPs]);
/* initialize ioporder structures */
/* InitializeCondition( &(order->iopo_cv), ... ); (individually!) */
order->iopo_done = IOPODONE_INIT;
order->iopo_next = NIL;
order->iopo_cancel = NIL;
order->iopo_proc = remoteProc;
(void) bzero( ((char *)(order->iopo_results)),
(sizeof order->iopo_results) );
for( i = 0; i < XR_maxIOPs; i++ ) {
iopo = &(iopor[i]);
(void) bcopy( ((char *)(order)), ((char *)(iopo)),
sizeof(struct XR_IOPOrderRep) );
XR_InitializeCondition( &(iopo->iopo_cv), XR_WAIT_FOREVER );
}
/* acquire all iop order locks */
if( XR_holderOfIOPOrderLocks != XR_currThread ) {
for( iope = XR_sysArea->sa_iope; iope < iopeLim; iope++ ) {
XR_MonitorEntry( &(iope->iope_orderLock) );
}
}
/* issue order to each iop */
for( i = 0; i < XR_maxIOPs; i++ ) {
iope = &(XR_sysArea->sa_iope[i]);
iopo = &(iopor[i]);
XR_ASSERT( (iope->iope_order == NIL), "IssueIOPOrders a0" );
if( localProc != NIL ) (*localProc)(iopo, iope);
iope->iope_order = iopo;
if( kill(iope->iope_pid, XR_SIG_RESCHED) < 0 )
XR_Panic("IssueIOPOrders 0");
}
/* wait for orders to be accepted by all iops */
for( iope = XR_sysArea->sa_iope; iope < iopeLim; iope++ ) {
ans = XR_WaitCV( &(iope->iope_orderAccepted), NIL );
if( ans != 0 ) XR_Panic("IssueIOPOrders 1a");
}
/* release all iop order locks */
if( XR_holderOfIOPOrderLocks != XR_currThread ) {
for( iope = XR_sysArea->sa_iope; iope < iopeLim; iope++ ) {
XR_MonitorExit( &(iope->iope_orderLock) );
}
}
/* wait for orders to be executed by all iops */
for( i = 0; i < XR_maxIOPs; i++ ) {
iope = &(XR_sysArea->sa_iope[i]);
iopo = &(iopor[i]);
ans = XR_WaitCV( &(iopo->iopo_cv), NIL );
if( (ans == 0) && (iopo->iopo_done != IOPODONE_INIT) ) {
int prevRes, res;
while( iopo->iopo_done != IOPODONE_DONE ) {
XR_SpinStep(1000);
}
prevRes = (int)(order->iopo_results[0]);
res = (int)(iopo->iopo_results[0]);
if( (prevRes == 0) || (res < 0) ) {
(void) bcopy( ((char *)(iopo->iopo_results)),
((char *)(order->iopo_results)),
(sizeof order->iopo_results) );
}
} else {
XR_Panic("IssueIOPOrders 1b");
}
}
return XR_IOPO_RESULT_OK;
}
void
XR_NotifyIOPODone(iopo)
XR_IOPOrder iopo;
{
XR_VPE vpe;
XR_ASSERT((!(iopo->iopo_done)), "NotifyIOPODone a0");
XR_ASSERT((!(iopo->iopo_cv.cv_wakeupWaiting)), "NotifyIOPODone a1");
iopo->iopo_done = IOPODONE_FINISHING;
vpe = XR_NakedNotifyInner( &(iopo->iopo_cv) );
iopo->iopo_done = IOPODONE_DONE;
if( vpe != NIL ) XR_RequestResched(vpe);
}